package com.hymjweb.demo.hymj.master_bill_manage.pull.service;

import com.alibaba.fastjson.JSONObject;
import com.hymjweb.demo.framework.result.MIniUIGridResultMap;
import com.hymjweb.demo.framework.sys.BaseService;
import com.hymjweb.demo.framework.sys.SysConstant;
import com.hymjweb.demo.framework.util.DataTypeUtil;
import com.hymjweb.demo.framework.util.DoubleUtil;
import com.hymjweb.demo.hymj.log_manage.aop.annotation.OperationLogger;
import com.hymjweb.demo.hymj.master_bill_manage.auto.bean.BMasterBillAutoPojo;
import com.hymjweb.demo.hymj.master_bill_manage.auto.service.BMasterBillAutoService;
import com.hymjweb.demo.hymj.master_bill_manage.flight.bean.BMasterBillFlightPojo;
import com.hymjweb.demo.hymj.master_bill_manage.flight.service.BMasterBillFlightService;
import com.hymjweb.demo.hymj.master_bill_manage.load.bean.BNativeBillLoadPojo;
import com.hymjweb.demo.hymj.master_bill_manage.load.service.BNativeBillLoadService;
import com.hymjweb.demo.hymj.master_bill_manage.pull.bean.BMasterBillPullPojo;
import com.hymjweb.demo.hymj.master_bill_manage.pull.detail.bean.BMasterBillPullDetailPojo;
import com.hymjweb.demo.hymj.master_bill_manage.pull.detail.service.BMasterBillPullDetailService;
import com.hymjweb.demo.hymj.master_bill_manage.pull.mapper.BMasterBillPullMapper;
import com.hymjweb.demo.hymj.native_bill_manage.bean.BNativeBillPojo;
import com.hymjweb.demo.hymj.native_bill_manage.pull_cost.bean.BNativeBillPullCostPojo;
import com.hymjweb.demo.hymj.native_bill_manage.pull_cost.service.BNativeBillPullCostService;
import com.hymjweb.demo.hymj.native_bill_manage.service.BNativeBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
public class BMasterBillPullService extends BaseService {

    @Autowired
    private BMasterBillPullMapper bMasterBillPullMapper;

    @Autowired
    private BNativeBillLoadService bNativeBillLoadService;

    @Autowired
    private BNativeBillService bNativeBillService;

    @Autowired
    private BMasterBillPullDetailService bMasterBillPullDetailService;

    @Autowired
    private BMasterBillFlightService bMasterBillFlightService;

    @Autowired
    private BMasterBillAutoService bMasterBillAutoService;

    @Autowired
    private BNativeBillPullCostService bNativeBillPullCostService;

    public Object getPageList(Map param) {
        // 设置公共查询参数,加上部门
        this.setQueryCommParam(param);
        this.pageListInit(param);
        List list = bMasterBillPullMapper.findAll(param);
        MIniUIGridResultMap resultMap = this.pageToGrid(list);
        return resultMap;
    }


    public BMasterBillPullPojo getBMasterBillPullPojoByMasterBillIdAndBillTypeId(String masterBillId, Long billTypeId) {
        return bMasterBillPullMapper.getBMasterBillPullPojoByMasterBillIdAndBillTypeId(masterBillId, billTypeId);
    }

    /**
     * 拉货对象转object
     *
     * @param jsonObject
     * @return
     */
    public BMasterBillPullPojo jsonObjConvertToPojo(JSONObject jsonObject) {

        BMasterBillPullPojo pojo = jsonObject.toJavaObject(BMasterBillPullPojo.class);

        // 1.生成b_master_bill_pull对象 ID
        pojo.setId(this.getSysStrId());
        // 设置日期与处理人
        Date currentDate = this.getSysTime();
        String czyId = this.getLoginCzyId();
        pojo.setCreateTime(currentDate);
        pojo.setCreateUserId(czyId);
        pojo.setUpdateTime(currentDate);
        pojo.setUpdateUserId(czyId);

        // 2.遍历子表，用于生成拉货detail 对象 b_master_bill_pull_detail
        List<BMasterBillPullDetailPojo> pullList = pojo.getPullList();

        for (BMasterBillPullDetailPojo detailPojo : pullList) {
            // 设置每个明细的关键字段
            // 设置明细id
            detailPojo.setId(this.getSysStrId());
            // 设置明细对象关联的主对象 id
            detailPojo.setMasterBillPullId(pojo.getId());
        }

        return pojo;
    }

    //@OperationLogger(oper = SysConstant.OPER_ADD, operTitle = "主单拉货-新增", operMemo = "", classType = BMasterBillPullPojo.class)
    @Transactional(rollbackFor = {Exception.class})
    public int insert(BMasterBillPullPojo bMasterBillPullPojo) throws Exception {
        if (bMasterBillPullPojo == null) {
            throwException("主单拉货对象为空，拉货操作失败!");
        }
        return bMasterBillPullMapper.insert(bMasterBillPullPojo);
    }

    @Transactional(rollbackFor = {Exception.class})
    public int delete(String id) throws Exception {
        if (DataTypeUtil.isEmptyStr(id)) {
            throwException("删除拉货主表对象参数错误");
        }
        return bMasterBillPullMapper.delete(id);
    }


    @Transactional(rollbackFor = {Exception.class})
    public int deleteByMasterBillId(String masterBillId) throws Exception {
        if (DataTypeUtil.isEmptyStr(masterBillId)) {
            throwException("删除拉货主表对象主单号参数错误");
        }

        return bMasterBillPullMapper.deleteByMasterBillId(masterBillId);
    }


    /**
     * 拉货对象入库
     *
     * @param bMasterBillPullPojo
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public int pullIntoDb(BMasterBillPullPojo bMasterBillPullPojo) throws Exception {

        int effectRows = 1;

        // 获取主单原始配载对象,准备用于记录主单全拉退回客户及全拉改配时记录使用
        List<BNativeBillLoadPojo> originalLoadPojoList = bNativeBillLoadService.queryNativeBillListByMasterBillId(bMasterBillPullPojo.getMasterBillId());

        // 1.拉货主对象入库 b_master_bill_pull 表 ,暂不用代理
        int billPullAffectRows = this.insert(bMasterBillPullPojo);

        // 2.拉货明细对象入库 b_master_bill_pull_detail
        List<BMasterBillPullDetailPojo> bMasterBillPullDetailPojoList = bMasterBillPullPojo.getPullList();
        int bullPullDetailAffectRows = bMasterBillPullDetailService.batchInsert(bMasterBillPullDetailPojoList);

        // 3.根据 bMasterBillPullPojo 调整 b_master_bill_auto 或 b_master_bill_flight 表中对应对象的信息
        Long masterBillTypeId = bMasterBillPullPojo.getMasterBillTypeId();
        String masterBillId = bMasterBillPullPojo.getMasterBillId();
        // 班次名称
        String masterBillFlightName = null;
        // 班次日期
        Date flightDate = null;

        // 记录主前单必要信息
        // 主单原始结算费
        Double masterBillOriginalSettlementAmount = 0D;
        Double masterBillOriginalChargeableWeight = 0D;
        Long masterBillOriginalTotalNumber = 0L;
        Integer masterBillOriginalCostShareStandard = 0;

        // 操作员及日期
        String czyId = this.getLoginCzyId();
        Date currentTime = this.getSysTime();

        // 根据主单类型调整不同的主单对象
        if (masterBillTypeId.longValue() == SysConstant.XT_DIC_MASTER_BILL_TYPE.FLIGHT.getId()) {
            // 这是需要更新 b_master_bill_flight 表中的对象
            BMasterBillFlightPojo bMasterBillFlightPojo = bMasterBillFlightService.getBMasterBillFlightPojoById(masterBillId);
            // 设置BMasterBillFlightPojo对象拉货状态为已拉货
            bMasterBillFlightPojo.setDropStatusId(SysConstant.XT_DIC_PULL_STATUS.PULL.getId());
            // 设置BMasterBillFlightPojo对象拉货金额为bMasterBillPullPojo对应的拉货调整金额
            bMasterBillFlightPojo.setDropAmount(bMasterBillPullPojo.getPullDisposeAmount());
            // 设置BMasterBillFlightPojo对象结算金额为 BMasterBillFlightPojo 总金额 + BMasterBillFlightPojo 调整金额
            bMasterBillFlightPojo.setSettlementAmount(DoubleUtil.sum(bMasterBillFlightPojo.getTotalAmount(), bMasterBillFlightPojo.getDropAmount(), 2));
            // 设置 BMasterBillFlightPojo 结算状态为未结算
            bMasterBillFlightPojo.setSettlementStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.UNCLEARED.getId());
            // 设置 pull_dispose_transport_cost_amount
            bMasterBillFlightPojo.setPullDisposeTransportCostAmount(bMasterBillPullPojo.getPullDisposeTransportCostAmount());
            // 设置 pull_dispose_ground_amount
            bMasterBillFlightPojo.setPullDisposeGroundAmount(bMasterBillPullPojo.getPullDisposeGroundAmount());
            // 设置 pull_dispose_airlines_add_cost_amount
            bMasterBillFlightPojo.setPullDisposeAirlinesAddCostAmount(bMasterBillPullPojo.getPullDisposeAirlinesAddCostAmount());
            // 设置 pullDisposeOtherChargesAmount
            bMasterBillFlightPojo.setPullDisposeOtherChargesAmount(bMasterBillPullPojo.getPullDisposeOtherChargesAmount());

            // transportCostStatusId
            if (DoubleUtil.sum(bMasterBillFlightPojo.getTransportCost(), bMasterBillFlightPojo.getPullDisposeTransportCostAmount(), 2) == 0) {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            } else {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.UNCLEARED.getId());
            }

            // groundAmountStatusId
            if (DoubleUtil.sum(bMasterBillFlightPojo.getGroundAmount(), bMasterBillFlightPojo.getPullDisposeGroundAmount(), 2) == 0) {
                bMasterBillFlightPojo.setGroundAmountStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            } else {
                bMasterBillFlightPojo.setGroundAmountStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.UNCLEARED.getId());
            }
            // 拉过货的把拉货备注回写到到主单对象
            String masterBillComment = bMasterBillFlightPojo.getComment();
            if (masterBillComment != null) {
                masterBillComment += " / " + bMasterBillPullPojo.getPullDisposeComment();
            } else {
                masterBillComment = bMasterBillPullPojo.getPullDisposeComment();
            }
            bMasterBillFlightPojo.setComment(masterBillComment);

            bMasterBillFlightPojo.setUpdateUserId(czyId);
            bMasterBillFlightPojo.setUpdateTime(currentTime);

            masterBillFlightName = bMasterBillFlightPojo.getFlightName();
            flightDate = bMasterBillFlightPojo.getFlightDate();

            /**
             *  Double masterBillSettlementAmount = 0D;
             *         Double masterBillChargeableWeight = 0D;
             *         Long masterBillTotalNumber = 0L;
             */

            masterBillOriginalSettlementAmount = bMasterBillFlightPojo.getSettlementAmount();
            masterBillOriginalChargeableWeight = bMasterBillFlightPojo.getChargeableWeight();
            masterBillOriginalTotalNumber = bMasterBillFlightPojo.getTotalNumber();

            masterBillOriginalCostShareStandard = bMasterBillFlightService.getCostShareStandard(bMasterBillFlightPojo,originalLoadPojoList);

            // 更新对象
            int updateFlightPojoAffectRows = bMasterBillFlightService.updatePojo(bMasterBillFlightPojo);
        } else {
            // 这是需要更新 b_master_bill_auto 表中的对象
            BMasterBillAutoPojo bMasterBillAutoPojo = bMasterBillAutoService.getBMasterBillAutoPojoById(masterBillId);

            // 设置BMasterBillAutoPojo对象拉货状态为已拉货
            bMasterBillAutoPojo.setDropStatusId(SysConstant.XT_DIC_PULL_STATUS.PULL.getId());
            // 设置BMasterBillAutoPojo对象拉货金额为bMasterBillPullPojo对应的拉货调整金额
            bMasterBillAutoPojo.setDropAmount(bMasterBillPullPojo.getPullDisposeAmount());
            // 设置BMasterBillAutoPojo对象结算金额为 BMasterBillFlightPojo 总金额 + BMasterBillFlightPojo 调整金额
            bMasterBillAutoPojo.setSettlementAmount(DoubleUtil.sum(bMasterBillAutoPojo.getTotalFreightAmount(), bMasterBillAutoPojo.getDropAmount(), 2));
            // 设置 BMasterBillAutoPojo 结算状态为未结算
            bMasterBillAutoPojo.setSettlementStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.UNCLEARED.getId());

            // 拉过货的把拉货备注回写到到主单对象
            String masterBillComment = bMasterBillAutoPojo.getComment();
            if (masterBillComment != null) {
                masterBillComment += " / " + bMasterBillPullPojo.getPullDisposeComment();
            } else {
                masterBillComment = bMasterBillPullPojo.getPullDisposeComment();
            }
            bMasterBillAutoPojo.setComment(masterBillComment);

            bMasterBillAutoPojo.setUpdateUserId(czyId);
            bMasterBillAutoPojo.setUpdateTime(currentTime);

            masterBillFlightName = bMasterBillAutoPojo.getLicensePlateNumber();
            flightDate = bMasterBillAutoPojo.getDeliveryTime();

            /**
             *  Double masterBillSettlementAmount = 0D;
             *         Double masterBillChargeableWeight = 0D;
             *         Long masterBillTotalNumber = 0L;
             */

            masterBillOriginalSettlementAmount = bMasterBillAutoPojo.getSettlementAmount();
            masterBillOriginalChargeableWeight = bMasterBillAutoPojo.getChargeableWeight();
            masterBillOriginalTotalNumber = bMasterBillAutoPojo.getTotalNumber();

            masterBillOriginalCostShareStandard = bMasterBillAutoService.getCostShareStandard(bMasterBillAutoPojo,originalLoadPojoList);

            int updateAutoPojoAffectRows = bMasterBillAutoService.update(bMasterBillAutoPojo);
        }

        // 4.处理 b_native_bill_load 表中信息,这个要根据 bMasterBillPullDetailPojoList 列中对于分单的不同处理规则进行处理
        // 4.1 处理说明:根据拉货处理规则，不论是什么样的处置方式（补发、改配、退客户或没有对某个分单选择处理方式）都需要对象原始的配载对象进行配载信息的更新与配载成本的重新核算（因为主单的价格变了）
        for (BMasterBillPullDetailPojo pullDetailPojo : bMasterBillPullDetailPojoList) {

            // 4.2 检索到原来的配载对象 pullDetailPojo.getAssociationLoadId() 是配载表的ID
            BNativeBillLoadPojo bNativeBillLoadPojo = bNativeBillLoadService.queryBNativeBillLoadPojoById(pullDetailPojo.getAssociationLoadId());

            if (bNativeBillLoadPojo == null) {
                throwException("拉货获取分单原始配载对象为空!");
            }

            // 4.3 根据拉货明细调整源原始配载对象上的配载件数、配载实重、配载计重、配载体积信息
            // 4.3.1 配载件数减少
            long nativeLoadTotalNumber = bNativeBillLoadPojo.getLoadNumber(); // 记录配载对象没有调整之前的配载件数
            bNativeBillLoadPojo.setLoadNumber(bNativeBillLoadPojo.getLoadNumber() - pullDetailPojo.getPullNumber()); // 根据拉货明细调整配载件数
            // 4.3.2 配载实重减少
            double nativeLoadActualWeight = bNativeBillLoadPojo.getLoadActualWeight(); // 记录配载对象没有调整之前的配载实重
            bNativeBillLoadPojo.setLoadActualWeight(DoubleUtil.sub(bNativeBillLoadPojo.getLoadActualWeight(), pullDetailPojo.getPullActualWeight(), 2)); // 根据拉货明细调整配载实重
            // 4.3.3 配载计重新减少
            double nativeLoadChargeableWeight = bNativeBillLoadPojo.getLoadChargeableWeight(); // 记录配载对象没有调整之前的配载计重
            bNativeBillLoadPojo.setLoadChargeableWeight(DoubleUtil.sub(bNativeBillLoadPojo.getLoadChargeableWeight(), pullDetailPojo.getPullChargeableWeight(), 2)); // 根据拉货明细调整配载计重
            // 4.3.4 配载体积减少
            double nativeLoadVolume = bNativeBillLoadPojo.getLoadVolume(); // 记录配载对象没有调整之前的配载体积
            bNativeBillLoadPojo.setLoadVolume(DoubleUtil.sub(bNativeBillLoadPojo.getLoadVolume(), pullDetailPojo.getPullVolume(), 2)); // 根据拉货明细调整配载体积

            // 1.获取配载信息的原始分单对象
            BNativeBillPojo bNativeBillPojo = bNativeBillService.getBNativeBillPojoById(bNativeBillLoadPojo.getNativeBillId());

            // 设置分单的调整金额
            bNativeBillPojo.setDropAmount(pullDetailPojo.getPullAmount());
            // 设置分单的结算金额为实收金额加上调整金额
            bNativeBillPojo.setSettlementAmount(DoubleUtil.sum(bNativeBillPojo.getActualAmount(),bNativeBillPojo.getDropAmount(),2));

            // 4.清除原始分单对象上的成本利润
            bNativeBillPojo.setShareCost(0D);
            bNativeBillPojo.setGrossProfit(0D);
            bNativeBillPojo.setShareCostComment("");

            // 3.调整原始对象的拉货状态
            bNativeBillPojo.setDropStatusId(SysConstant.XT_DIC_PULL_STATUS.PULL.getId());

            // 4.4.5 如果分单配载对象调整后的配载件数为0,则表示是全拉货 如果是全拉改配 或 全拉退货,则全需要删除原始的配载信息,同时调整原始分单上的配载状态或退回信息
            if (bNativeBillLoadPojo.getLoadNumber() == 0) {
                // 5.这是全拉货
                // 5.1 全拉货还分三种，全拉补发，全拉改配，全拉退客户
                if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.SUPPLY.getId()) {
                    // 5.1 全拉补发
                    // 5.1.1 全拉补发，直接更新原始的配载信息
                    // 5.1.2 恢复拉货分单原始信息
                    bNativeBillLoadPojo.setLoadNumber(nativeLoadTotalNumber);
                    bNativeBillLoadPojo.setLoadActualWeight(nativeLoadActualWeight);
                    bNativeBillLoadPojo.setLoadChargeableWeight(nativeLoadChargeableWeight);
                    bNativeBillLoadPojo.setLoadVolume(nativeLoadVolume);

                    // 5.1.3 设置全拉补发到调整后的班次信息
                    bNativeBillLoadPojo.setAirlinesId(pullDetailPojo.getPullDisposeAirlinesId());
                    bNativeBillLoadPojo.setFlightNo(pullDetailPojo.getPullDisposeFlightNo());
                    bNativeBillLoadPojo.setFlightName(pullDetailPojo.getPullDisposeFlightName());
                    bNativeBillLoadPojo.setFlightDate(pullDetailPojo.getPullDisposeFlightDate());

                    // 5.1.4 调整全拉后的分摊成本为0,后面会进行重新进行成本核算
                    bNativeBillLoadPojo.setShareTransportCostAmount(0D);
                    bNativeBillLoadPojo.setShareGroundAmount(0D);
                    bNativeBillLoadPojo.setShareAirlinesAddCostAmount(0D);
                    bNativeBillLoadPojo.setShareOtherChargesAmount(0D);
                    bNativeBillLoadPojo.setShareTotalCostAmount(0D);
                    bNativeBillLoadPojo.setShareTotalCostComment("");

                    // 5.1.5 更新全新配载信息
                    bNativeBillLoadService.update(bNativeBillLoadPojo);
                }

                // 6.全拉改配或全拉退客户
                if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.RELOAD.getId()
                        ||
                        pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.REFUND.getId()) {
                    // 6.1 全拉改配或全拉退客户直接删除原始的配载对象
                    bNativeBillLoadService.delete(bNativeBillLoadPojo.getId());

                    // 6.2 修改配载状态为未配载
                    bNativeBillPojo.setBillLoadStatusId(SysConstant.XT_DIC_BILL_LOAD_STATUS.NO_LOAD.getId());

                    // 6.3 如覃全拉退客户时需要调整退回信息
                    if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.REFUND.getId()) {
                        // 6.3.1 全拉退客户,设置原始分单上退客户件数、实重、计重、体积信息
                        bNativeBillPojo.setRefundNumber(pullDetailPojo.getPullNumber().intValue());
                        bNativeBillPojo.setRefundActualWeight(pullDetailPojo.getPullActualWeight());
                        bNativeBillPojo.setRefundChargeableWeight(pullDetailPojo.getPullChargeableWeight());
                        bNativeBillPojo.setRefundVolume(pullDetailPojo.getPullVolume());
                        // 调整拉货金额
                        bNativeBillPojo.setDropAmount(pullDetailPojo.getPullAmount());
                        // 调整结算金额
                        bNativeBillPojo.setSettlementAmount(DoubleUtil.sum(bNativeBillPojo.getActualAmount(), bNativeBillPojo.getDropAmount(), 2));
                    }


                    // 6.4 需要记录对应的拉货产生的成本，注意必须是主单结算费用大于零时才记录，不大于零就不用记录了
                    if(masterBillOriginalSettlementAmount.doubleValue()>SysConstant.ZERO.doubleValue()){
                        Double sharePercent = SysConstant.ZERO;

                        // 计算分摊成本
                        if(masterBillOriginalCostShareStandard.intValue() == SysConstant.COST_SHARE_STANDARD_WEIGHT.intValue()){
                            Double loadChargeableWeight = SysConstant.ZERO;
                            for(BNativeBillLoadPojo loadPojo: originalLoadPojoList){
                                if(loadPojo.getNativeBillId().equals(pullDetailPojo.getNativeBillId())){
                                    loadChargeableWeight = loadPojo.getLoadChargeableWeight();
                                    break;
                                }
                            }
                            // 按重量分摊
                            sharePercent = DoubleUtil.div(loadChargeableWeight,masterBillOriginalChargeableWeight,2);

                        }
                        else{
                            // 按件数分摊
                            Long loadNumber = 0L;
                            for(BNativeBillLoadPojo loadPojo: originalLoadPojoList){
                                if(loadPojo.getNativeBillId().equals(pullDetailPojo.getNativeBillId())){
                                    loadNumber = loadPojo.getLoadNumber();
                                    break;
                                }
                            }
                            sharePercent = DoubleUtil.div(loadNumber*1.0,masterBillOriginalTotalNumber*1.0,2);
                        }

                        BNativeBillPullCostPojo bNativeBillPullCostPojo = new BNativeBillPullCostPojo();
                        bNativeBillPullCostPojo.setId(this.getSysStrId());
                        bNativeBillPullCostPojo.setMasterBillId(bNativeBillLoadPojo.getMasterBillId());
                        bNativeBillPullCostPojo.setMasterBillTypeId(bNativeBillLoadPojo.getMasterBillTypeId());
                        bNativeBillPullCostPojo.setNativeBillId(pullDetailPojo.getNativeBillId());
                        bNativeBillPullCostPojo.setNativePullDisposeId(pullDetailPojo.getPullDisposeId());
                        bNativeBillPullCostPojo.setCostShareStandard(masterBillOriginalCostShareStandard);
                        bNativeBillPullCostPojo.setCostSharePercent(sharePercent);
                        bNativeBillPullCostPojo.setCostShareAmount(DoubleUtil.mul(masterBillOriginalSettlementAmount,sharePercent,2));
                        bNativeBillPullCostPojo.setCreateTime(currentTime);
                        bNativeBillPullCostPojo.setCreateUserId(czyId);
                        bNativeBillPullCostPojo.setUpdateTime(currentTime);
                        bNativeBillPullCostPojo.setUpdateUserId(czyId);


                        // 调用入库
                        int pullCostAffectRows = bNativeBillPullCostService.insert(bNativeBillPullCostPojo);
                    }
                }

            } else {
                // 这是部分拉货
                // 1.直接更新上面调整后的配载信息
                bNativeBillLoadService.update(bNativeBillLoadPojo);
                // 部分拉货还分三种，部分拉货补发，部分拉货改配，部分拉货退客户
                if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.SUPPLY.getId()) {
                    // 部分拉货补发 那么需要新成生一个配载对象，并做成本核算后记入配载表
                    BNativeBillLoadPojo newBillLoadPojo = new BNativeBillLoadPojo();
                    newBillLoadPojo.setId(this.getSysStrId());
                    newBillLoadPojo.setMasterBillId(masterBillId);
                    newBillLoadPojo.setMasterBillTypeId(masterBillTypeId);
                    newBillLoadPojo.setNativeBillId(pullDetailPojo.getNativeBillId());
                    newBillLoadPojo.setAirlinesId(pullDetailPojo.getPullDisposeAirlinesId());
                    newBillLoadPojo.setFlightNo(pullDetailPojo.getPullDisposeFlightNo());
                    newBillLoadPojo.setFlightName(pullDetailPojo.getPullDisposeFlightName());
                    newBillLoadPojo.setFlightDate(pullDetailPojo.getPullDisposeFlightDate());
                    newBillLoadPojo.setLoadNumber(pullDetailPojo.getPullNumber());
                    newBillLoadPojo.setLoadActualWeight(pullDetailPojo.getPullActualWeight());
                    newBillLoadPojo.setLoadChargeableWeight(pullDetailPojo.getPullChargeableWeight());
                    newBillLoadPojo.setLoadVolume(pullDetailPojo.getPullVolume());
                    newBillLoadPojo.setShareTransportCostAmount(0D);
                    newBillLoadPojo.setShareGroundAmount(0D);
                    newBillLoadPojo.setShareAirlinesAddCostAmount(0D);
                    newBillLoadPojo.setShareOtherChargesAmount(0D);
                    newBillLoadPojo.setShareTotalCostAmount(0D);
                    newBillLoadPojo.setShareTotalCostComment("");
                    // 4.5.2 添加新的对象到到配载表中
                    bNativeBillLoadService.insert(newBillLoadPojo);
                }

                if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.RELOAD.getId()) {
                    // 部分拉货改配
                    bNativeBillPojo.setBillLoadStatusId(SysConstant.XT_DIC_BILL_LOAD_STATUS.PART_LOAD.getId());
                }

                if (pullDetailPojo.getPullDisposeId().longValue() == SysConstant.XT_DIC_NATIVE_PULL_DISPOSE.REFUND.getId()) {
                    // 部分拉货退客户
                    bNativeBillPojo.setRefundNumber(pullDetailPojo.getPullNumber().intValue());
                    bNativeBillPojo.setRefundActualWeight(pullDetailPojo.getPullActualWeight());
                    bNativeBillPojo.setRefundChargeableWeight(pullDetailPojo.getPullChargeableWeight());
                    bNativeBillPojo.setRefundVolume(pullDetailPojo.getPullVolume());
                }
            }

            // 2.调整分单上的更新日期与更新人
            bNativeBillPojo.setUpdateTime(currentTime);
            bNativeBillPojo.setUpdateUserId(czyId);

            // 7.更新原始分单
            bNativeBillService.update(bNativeBillPojo);
        }


        // 获取主单当前计费重量
        Double masterBillChargeableWeight = 0D;
        if (masterBillTypeId.longValue() == SysConstant.XT_DIC_MASTER_BILL_TYPE.FLIGHT.getId()) {
            BMasterBillFlightPojo bMasterBillFlightPojo = bMasterBillFlightService.getBMasterBillFlightPojoById(masterBillId);
            // 这是主单拉货后的计费重量
            masterBillChargeableWeight = DoubleUtil.sub(bMasterBillFlightPojo.getChargeableWeight(), bMasterBillPullPojo.getPullDisposeChargeableWeight(), 2);
        } else {
            BMasterBillAutoPojo bMasterBillAutoPojo = bMasterBillAutoService.getBMasterBillAutoPojoById(masterBillId);
            // 这是主单拉货后的计费重量
            masterBillChargeableWeight = DoubleUtil.sub(bMasterBillAutoPojo.getChargeableWeight(), bMasterBillPullPojo.getPullDisposeChargeableWeight(), 2);
        }

        // 获取主单配载分单列表
        List<BNativeBillLoadPojo> loadPojoList = bNativeBillLoadService.queryNativeBillListByMasterBillId(masterBillId);
        if (loadPojoList != null && !loadPojoList.isEmpty()) {
            // 遍历一下，瞧一瞧整体或个体重量是否超过主单计费重量
            boolean flag = false;
            Double loadPojoTotalChargeableWeight = 0D;
            for (BNativeBillLoadPojo loadPojo : loadPojoList) {
                if (loadPojo.getLoadChargeableWeight() > masterBillChargeableWeight) {
                    // 如果有一个配载分单的重量大于主单重量，就直接退出
                    flag = true;
                    break;
                }
                loadPojoTotalChargeableWeight += loadPojo.getLoadChargeableWeight();
            }

            // 默认是按重量进行分摊
            Integer costShareStandard = SysConstant.COST_SHARE_STANDARD_WEIGHT;
            // 如果主单下的某个分单的配载重量大于主单重量，或配载分单的总重量大于主单的重量，则采用件数标准进行分摊成本核算
            if (loadPojoTotalChargeableWeight > masterBillChargeableWeight || flag) {
                costShareStandard = SysConstant.COST_SHARE_STANDARD_NUMBER;
            }

            // 核算每配载分单的成本
            for (BNativeBillLoadPojo loadPojo : loadPojoList) {
                bNativeBillLoadService.loadNativeBillCostAccounting(loadPojo, costShareStandard);
            }

            effectRows = 0;
            // 分单成本核算并保存入库
            for (BNativeBillLoadPojo loadPojo : loadPojoList) {
                effectRows += bNativeBillService.nativeBillCostAccounting(loadPojo.getNativeBillId(), true);
            }
        }

        return effectRows;
    }


    @Transactional(rollbackFor = {Exception.class})
    public int update(BMasterBillPullPojo bMasterBillPullPojo) throws Exception {
        if (bMasterBillPullPojo == null) {
            throwException("主单拉货对象更新参数错误!");
        }
        return bMasterBillPullMapper.update(bMasterBillPullPojo);
    }


    /**
     * 主单拉货对象更新处理
     *
     * @param bMasterBillPullPojo
     * @return
     */
    @Transactional(rollbackFor = {Exception.class})
    public int updatePullIntoDb(BMasterBillPullPojo bMasterBillPullPojo) throws Exception {
        // 1.更新b_master_bill_pull表中对应记录
        if (bMasterBillPullPojo == null) {
            throwException("主单拉货对象更新参数错误!");
        }
        int updateAffectRows = update(bMasterBillPullPojo);

        // 2.根据主单号调整金额检索b_master_bill_flight或b_master_bill_auto，得到原始主单对象，并更新
        String masterBillId = bMasterBillPullPojo.getMasterBillId();
        Long masterBillTypeId = bMasterBillPullPojo.getMasterBillTypeId();

        // 记录主前单必要信息
        // 主单原始结算费
        Double masterBillOriginalSettlementAmount = 0D;
        Double masterBillOriginalChargeableWeight = 0D;
        Long masterBillOriginalTotalNumber = 0L;
        Integer masterBillOriginalCostShareStandard = 0;

        String czyId = this.getLoginCzyId();
        Date currentTime = this.getSysTime();

        BMasterBillFlightPojo bMasterBillFlightPojo = null;
        BMasterBillAutoPojo bMasterBillAutoPojo = null;

        if (masterBillTypeId.longValue() == SysConstant.XT_DIC_MASTER_BILL_TYPE.FLIGHT.getId()) {
            // b_master_bill_flight
            // pullDisposeTransportCostAmount   transportCostStatusId
            // pullDisposeGroundAmount  groundAmountStatusId
            // pullDisposeAirlinesAddCostAmount
            // pullDisposeOtherChargesAmount
            // drop_amount
            // settlementAmount  settlementStatusId
            // comment

            bMasterBillFlightPojo = bMasterBillFlightService.getBMasterBillFlightPojoById(masterBillId);

            bMasterBillFlightPojo.setPullDisposeTransportCostAmount(bMasterBillPullPojo.getPullDisposeTransportCostAmount());
            bMasterBillFlightPojo.setPullDisposeGroundAmount(bMasterBillPullPojo.getPullDisposeGroundAmount());
            bMasterBillFlightPojo.setPullDisposeAirlinesAddCostAmount(bMasterBillPullPojo.getPullDisposeAirlinesAddCostAmount());
            bMasterBillFlightPojo.setPullDisposeOtherChargesAmount(bMasterBillPullPojo.getPullDisposeOtherChargesAmount());
            bMasterBillFlightPojo.setDropAmount(bMasterBillPullPojo.getPullDisposeAmount());

            bMasterBillFlightPojo.setSettlementAmount(DoubleUtil.sum(bMasterBillFlightPojo.getTotalAmount(), bMasterBillFlightPojo.getDropAmount(), 2));

            bMasterBillFlightPojo.setComment(bMasterBillFlightPojo.getComment() + " / " + bMasterBillPullPojo.getPullDisposeComment());

            if (DoubleUtil.sum(bMasterBillFlightPojo.getTransportCost(), bMasterBillFlightPojo.getPullDisposeTransportCostAmount(), 2) == 0D) {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            }

            if (DoubleUtil.sum(bMasterBillFlightPojo.getGroundAmount(), bMasterBillFlightPojo.getPullDisposeGroundAmount(), 2) == 0D) {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            }

            if (DoubleUtil.sum(bMasterBillFlightPojo.getAirlinesAddCost(), bMasterBillFlightPojo.getPullDisposeAirlinesAddCostAmount(), 2) == 0D) {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            }

            if (DoubleUtil.sum(bMasterBillFlightPojo.getOtherCharges(), bMasterBillFlightPojo.getPullDisposeOtherChargesAmount(), 2) == 0D) {
                bMasterBillFlightPojo.setTransportCostStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
            }

//            if(bMasterBillFlightPojo.getSettlementAmount() == 0D){
//                bMasterBillFlightPojo.setSettlementStatusId(SysConstant.XT_DIC_SETTLEMENT_STATUS.CLEARED.getId());
//            }

            bMasterBillFlightPojo.setUpdateUserId(czyId);
            bMasterBillFlightPojo.setUpdateTime(currentTime);

            masterBillOriginalSettlementAmount = bMasterBillFlightPojo.getSettlementAmount();
            masterBillOriginalChargeableWeight = bMasterBillFlightPojo.getChargeableWeight();
            masterBillOriginalTotalNumber = bMasterBillFlightPojo.getTotalNumber();

            int flightAffectRows = bMasterBillFlightService.updatePojo(bMasterBillFlightPojo);
        } else {
            // b_master_bill_auto
            // dropAmount
            // settlementAmount
            // settlementStatusId
            // 计算相相应的信息，并自动更新相应的状态

            bMasterBillAutoPojo = bMasterBillAutoService.getBMasterBillAutoPojoById(masterBillId);

            bMasterBillAutoPojo.setDropAmount(bMasterBillPullPojo.getPullDisposeAmount());
            bMasterBillAutoPojo.setSettlementAmount(DoubleUtil.sum(bMasterBillAutoPojo.getFreightAmount(), bMasterBillAutoPojo.getDropAmount(), 2));

            bMasterBillAutoPojo.setUpdateUserId(czyId);
            bMasterBillAutoPojo.setUpdateTime(currentTime);

            masterBillOriginalSettlementAmount = bMasterBillAutoPojo.getSettlementAmount();
            masterBillOriginalChargeableWeight = bMasterBillAutoPojo.getChargeableWeight();
            masterBillOriginalTotalNumber = bMasterBillAutoPojo.getTotalNumber();

            int autoAffectRows = bMasterBillAutoService.update(bMasterBillAutoPojo);
        }

        // 3.根据主单号加载对应的主单下的配置载信息得到配载列表
        Map<String, Object> param = new HashMap<>();
        param.put("masterBillId", masterBillId);
        param.put("masterBillTypeId", masterBillTypeId);
        List<BNativeBillLoadPojo> bNativeBillLoadPojoList = bNativeBillLoadService.queryNativeBillListNoPage(param);

        // 3.1 没有相应的分单，则不需要做成本重新核算
        if (bNativeBillLoadPojoList == null || bNativeBillLoadPojoList.isEmpty()) {

            // 3.1.1 配载分单没有说明全拉，检索b_native_bill_pull_cost表，获取对应的对象，做更新处理
            List<BNativeBillPullCostPojo> bNativeBillPullCostPojoList = bNativeBillPullCostService.queryListByMasterBillId(masterBillId);
            if(bNativeBillPullCostPojoList==null || bNativeBillPullCostPojoList.isEmpty()){
                return updateAffectRows;
            }

            // 开始分摊重新计算
            for(BNativeBillPullCostPojo costPojo : bNativeBillPullCostPojoList){
                Double sharePercent = costPojo.getCostSharePercent();
                costPojo.setCostShareAmount(DoubleUtil.mul(masterBillOriginalSettlementAmount,sharePercent,2));
                int pullCostPojoUpateAffectRows = bNativeBillPullCostService.update(costPojo);
            }

            return updateAffectRows;
        }

        Integer costShareStandard = null;
        if (masterBillTypeId.longValue() == SysConstant.XT_DIC_MASTER_BILL_TYPE.FLIGHT.getId()) {
            // 获取分单成本与利润核算标准
            costShareStandard = bMasterBillFlightService.getCostShareStandard(bMasterBillFlightPojo, bNativeBillLoadPojoList);

        } else {
            costShareStandard = bMasterBillAutoService.getCostShareStandard(bMasterBillAutoPojo, bNativeBillLoadPojoList);
        }

        // 4.根据配载列表的信息，重新核算分摊及成本
        for (BNativeBillLoadPojo pojo : bNativeBillLoadPojoList) {
            // 配载对象成本核算
            int loadCostAccountingAffectRows = bNativeBillLoadService.loadNativeBillCostAccounting(pojo, costShareStandard);
        }

        // 5.重新核算分单表中分单的利润及成配信息
        for (BNativeBillLoadPojo loadPojo : bNativeBillLoadPojoList) {
            int nativeUpdateAffectRows = bNativeBillService.nativeBillCostAccounting(loadPojo.getNativeBillId(), true);
        }

        return updateAffectRows;
    }



}
